/**
* @file		World.ixx
* @brief	代表整个世界
*
*
* @version	1.0
* @author	lveyou
* @date		22-03-06
*
* @note		以方正格子表示，以11.1公里为1格（1纬度约为111公里）
* @note		所以每格横向为0.1纬度，纵向为0.1经度
* @note		为了计算简单简便，我们所说的经纬度单位（称为LL)均乘10
* @note		longitude 经度，latitude 纬度，所以LL缩写为经纬度，但单位为10倍
* @note		以LL(1000, 300)作为原点XY_NODE_ZERO
* @note		LL范围为 [0, 3600), (-900, 900] （因为左上角为格子坐标，所以-900是开区间）
*/

export module World;

import DND;


import Node;
import DefVar;
import DefOrder;
import Medium.PanelGame;
import Database;
import MapTex;
import Facility;
import FacilityLocation;
import WorldTime;
import ResMgr;
import Area;
import Regime;
import Common;

constexpr std::string_view SL_PATH_TERRAIN = "map/default/terrain.dat";
constexpr std::string_view SL_PATH_FACILITY = "map/default/facility.dat";
constexpr std::string_view SL_PATH_AREA = "map/default/area.dat";

//! 缩放等级
constexpr array<real, 7> SCALE_LEVEL_ALL = { 0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.0 };



export class World
{
public:
	World();

	void Init()
	{
		Load(SL_PATH_TERRAIN);
		LoadFacility(SL_PATH_FACILITY);
		LoadArea(SL_PATH_AREA);

		RefreshAreaHasNode();
	}

	void Run(const LogicType& lt, const MediumPanelGame* md_panel_game);

	//class Block

	Node* AddNode(const Point& xy);

	void DeleteNode(const Point& xy);

	void DeleteFacility(const Point& xy);
	void DeleteArea(size_t uid);
	
	void Save(string_view path_name);
	void SaveFacility(string_view path_name);
	void SaveArea(string_view path_name);

	void Load(string_view path_name);
	void LoadFacility(string_view path_name);
	void LoadArea(string_view path_name);

	Coor* GetCoor() { return _coor; }

	//返回选中位置
	Point GetMouseXy()
	{
		Vector2 pos = toVector2(g_input->GetMousePosition());
		pos = _coor->WorldToThis(pos);
		
		return Pos2Xy(pos);
	}

	Vector2 Xy2Pos(const Point& xy)
	{
		return toVector2(xy) * DefVar::NODE_PIXEL;
	}

	Point Pos2Xy(const Vector2& pos)
	{
		Point xy = toPoint(pos / DefVar::NODE_PIXEL);
		if (pos[0] < 0) --xy[0];
		if (pos[1] < 0) --xy[1];
		return xy;
	}


	//返回节点，失败返回nullptr
	Node* GetNode(const Point& xy)
	{
		Node** ret = _allNode.Get(xy);
		return ret ? *ret : nullptr;
	}

	//返回选中（鼠标）节点，失败返回nullptr
	Node* GetMouseNode()
	{
		return GetNode(GetMouseXy());
	}

	//返回选中（锁定）设施
	Facility* GetSelectFacility()
	{
		return GetFacility(_selectFacility);
	}

	Facility* GetFacility(const Point& xy)
	{
		Facility** ret = _allFacility.Get(xy);
		return ret ? *ret : nullptr;
	}
	//更据位置查找附近的设施
	Facility* FindFacilityNear()
	{
		return nullptr;
	}

	//坐标到窗口（随时更新）
	Vector2 Xy2Window(const Point& xy, Horizontal h = Horizontal::LEFT, Vertical v = Vertical::TOP)
	{
		Vector2 pos = Xy2Pos(xy)
			- Size2AlignOffset(DefVar::SIZE_NODE_PIXEL, h, v);
		return _coor->ThisToWorld(pos);
	}

	Vector2 Xy2WindowCenter(const Point& xy)
	{
		return Xy2Window(xy, Horizontal::CENTER, Vertical::CENTER);
	}

	//返回刷子选中位置
	vector<Point> GetBrushXy(zahlen size);

	//地图坐标 -> 纹理坐标
	PointU Xy2MapTex(const Point& xy)
	{
		//先转到LL
		Point ll = Xy2Ll(xy);
		//LL转为纹理坐标
		Point out = LL2MapTex(xy);
		return Math::CastU(out);
	}

	//获取地形颜色
	Color GetTerrainColor(natural id)
	{
		return g_factory->GetColor("terrain_" + g_db->GetTerrainName(id));
	}

	//更新纹理地图
	void UpdateMapTex(const Node::SL& sl)
	{
		_mapTex.Set(Xy2MapTex(sl._xy), GetTerrainColor(sl._typeTerrain));
	}

	//添加设施
	Facility* AddFacility(const Point& xy, natural type)
	{
		Facility*& fac = _allFacility.Add(xy);
		if (fac == nullptr)
		{
			fac = new Facility({ xy, type });
			fac->RefreshUI();
		}
		return fac;
	}

	//返回时间信息
	WorldTime& GetAge() { return _worldTime; }

	//! 返回选中区域
	Area* GetSelectArea()
	{
		auto iter = _allArea.find(_uidAreaSelect);
		if (iter == _allArea.end())
			return nullptr;
		return iter->second;
	}

	real GetScale()
	{
		return SCALE_LEVEL_ALL[_curScaleLevel];
	}

	//----------------------------Area--------------------------

	//! 查找区域，失败返回nullptr
	Area* GetArea(size_t uid)
	{
		auto iter = _allArea.find(uid);
		if (iter == _allArea.end())
			return nullptr;
		return iter->second;
	}

	//! 更新区域 与 节点引用关系（加载后调用）
	void RefreshAreaHasNode()
	{
		for (auto& [uid, area] : _allArea)
		{//如果区域 拥有的 节点，已经指向其他区域，则删除引用，否则指向自己
			Area::SL& sl = area->GetSlRef();
			for (auto& iter : sl._allNode.GetContainer())
			{
				unordered_map<zahlen, Node*>& c = iter.second;

				for (auto iter1 = c.begin(); iter1 != c.end();)
				{
					Point xy = { iter1->first, iter.first };
					Node* node = GetNode(xy);
					if (node && node->GetTpRef()._uidArea == -1)
					{
						node->GetTpRef()._uidArea = uid;
						iter1->second = node;
						++iter1;
					}
					else
					{
						c.erase(iter1++);
					}
				}
			}
		}
	}

	~World()
	{
		//node
		for (auto& iter : _allNode.GetContainer())
		{
			for (auto& iter1 : iter.second)
			{
				delete iter1.second;
			}
		}

		//facility
		for (auto& iter : _allFacility.GetContainer())
		{
			for (auto& iter1 : iter.second)
			{
				delete iter1.second;
			}
		}

		//area
		for (auto& iter : _allArea)
		{
			delete iter.second;
		}

		//msgbox
		delete _msgBoxImportLocation;
	}
private:
	//根坐标系（不需要释放）
	Coor* _coor;
	//x, y -> node
	Hash2D<zahlen, Node*> _allNode;

	//x, y -> facility
	Hash2D<zahlen, Facility*> _allFacility;

	//uid -> 区域
	unordered_map<size_t, Area*> _allArea;
	size_t _uidArea;//使用id
	size_t _uidAreaSelect;//选择id

	//uid -> 势力
	unordered_map<size_t, Regime*> _allRegime;
	size_t _uidRegime;//使用id
	size_t _uidRegimeSelect;//选择id
	
	struct TP
	{
		bool _bRunEdit;
		vector<Point> _mulSelect;
	}_tp;

	//刷子和选中
	gcSprite _sprBrush;
	vector<gcSprite> _mulSprSelect;
	Quad _quadSelect;

	//缩放
	size_t _curScaleLevel;

	//网格
	Tool::Grid _grid;

	//纹理地图
	MapTex _mapTex;

	//设施刷子
	gcSprite _sprBrushFacility;
	//选中节点的设施（可能失效）
	Point _selectFacility;

	//选中区域的id（可能失效）
	size_t _selectArea;

	//时间（天为单位）
	WorldTime _worldTime;

	//导入定居点对话框
	Tool::MsgBox* _msgBoxImportLocation;

	void _update_coor();

	//选区逻辑
	void _update_select(zahlen size);

	void _render_select()
	{
		for (size_t i = 0; i < _tp._mulSelect.size(); ++i)
			_mulSprSelect[i]->Render();
	}
	//地形刷子逻辑
	void _update_brush(zahlen index,
		bool b_edit_water, bool b_new_node);

	void _render_brush()
	{
		if (_sprBrush)
			_sprBrush->Render();
	}

	//设施刷子逻辑
	void _update_brush_facility(zahlen index, bool b_delete);

	void _render_brush_facility()
	{
		if (_sprBrushFacility)
			_sprBrushFacility->Render();
	}

	//导入定居点
	void _import_location(natural tag);

	//区域逻辑
	void _update_area(size_t index);

	//势力逻辑
	void _update_regime(size_t index)
	{
		if (index < 1)
			return;
		if (index == 1)
		{//新增
			if (g_input->KeyDown(KeyCode::MOUSE_L))
			{
				size_t uid = _uidRegime++;
				Regime* regime = new Regime(uid);
				_allRegime.insert({ uid, regime });
			}
		}
	}
};

export World* g_world;

module :private;


World::World() :
	_grid{DefOrder::GRID, ColorDef::GREEN},
	_curScaleLevel{3},
	_msgBoxImportLocation{nullptr},
	_uidArea{0},
	_uidRegime{ 0 }
{
	_coor = g_factory->GetRootCoor(0);
	_mapTex.Init(_coor);

	_quadSelect = g_factory->CreateSprite("select")->GetQuad();

	_uidAreaSelect = -1;
	_uidRegime = -1;
}

void World::Run(const LogicType& lt, const MediumPanelGame* md_panel_game)
{
	if (lt.IsUpdate())
	{
		_update_coor();

		if (g_factory->GetOrderPickup() != 1.0f)
			_tp._bRunEdit = false;
		else
		{
			_tp._bRunEdit = true;

			_update_select(md_panel_game->_typeSize);
			_update_brush(
				md_panel_game->_typeTerrain,
				md_panel_game->_bEditWater,
				md_panel_game->_bNewNode);
			_update_brush_facility(
				md_panel_game->_typeFacility,
				md_panel_game->_bDeleteFacility
			);
			_update_area(md_panel_game->_indexArea);
			_update_regime(md_panel_game->_indexRegime);
		}

		//
		if (md_panel_game->_bRenderGrid)
		{
			Vector2 pos = _coor->ThisToWorld({});
			Vector2 size = fill_up<Vector2>(DefVar::NODE_PIXEL * md_panel_game->_sizeGrid)
				* _coor->GetScale();
			_grid.Update(pos, size);
		}


		if (md_panel_game->_indexMenu != -1)
		{
			auto index = md_panel_game->_indexMenu;
			if (index == 0)
			{
				Save(SL_PATH_TERRAIN);
			}
			else if (index == 1)
			{
				SaveFacility(SL_PATH_FACILITY);
			}
			else if (index == 2)
			{
				SaveArea(SL_PATH_AREA);
			}
		}

		//导入定居
		if (_msgBoxImportLocation)
		{
			//处理消息框
			_msgBoxImportLocation->Run(LogicType::UPDATE);
			size_t index = _msgBoxImportLocation->GetClick();
			if (index == 0)
			{//覆盖
				_import_location(0);
				delete _msgBoxImportLocation;
				_msgBoxImportLocation = nullptr;
			}
			else if (index == 1)
			{//保留
				_import_location(1);
				delete _msgBoxImportLocation;
				_msgBoxImportLocation = nullptr;
			}
			else if (index == 2 || _msgBoxImportLocation->IsClickClose())
			{//取消
				delete _msgBoxImportLocation;
				_msgBoxImportLocation = nullptr;
			}
		}
		else
		{//响应导入，弹出消息框
			if (md_panel_game->_indexImportLocation == 0)
			{
				_msgBoxImportLocation = g_res->CreateMsgBox("ImportLocation");
			}
		}
		
		//空区域删除
		vector<size_t> mul_uid;
		for (auto& [uid, area] : _allArea)
		{
			if (area->GetSL()._allNode.IsEmpty())
				mul_uid.push_back(uid);
		}
		for (auto& iter : mul_uid)
		{
			DeleteArea(iter);
		}
		

	}

	if (lt.IsRender())
	{
		//窗口范围，只绘制窗口内
		Point xy_lt = Pos2Xy(_coor->WorldToThis({}));
		Point xy_rb = Pos2Xy(_coor->WorldToThis(toVector2(g_system->GetWindowSize())));

		real s = SCALE_LEVEL_ALL[_curScaleLevel];
		if (s < 0.3)
		{
			_mapTex.Render();
		}
		else
		{
			//node
			for (auto& iter : _allNode.GetContainer())
			{
				zahlen y = iter.first;
				if (y < xy_lt[1] || y > xy_rb[1])
				{
					continue;
				}

				for (auto& iter1 : iter.second)
				{
					zahlen x = iter1.first;
					if (x < xy_lt[0] || x > xy_rb[0])
					{
						continue;
					}
					iter1.second->Render();
				}
			}
		}

		//area
		if (s < 0.5)
		{
			for (auto& iter : _allArea)
			{
				Area* area = iter.second;
				area->Render(s);
				//拾取操作
				if (_tp._bRunEdit
					&& g_input->KeyDown(KeyCode::MOUSE_L)
					&& area->IsPickup())
				{
					_uidAreaSelect = area->GetSL()._uid;
				}
			}
		}

		//facility
		for (auto& iter : _allFacility.GetContainer())
		{
			zahlen y = iter.first;
			if (y < xy_lt[1] || y > xy_rb[1])
			{
				continue;
			}

			for (auto& iter1 : iter.second)
			{
				zahlen x = iter1.first;
				if (x < xy_lt[0] || x > xy_rb[0])
				{
					continue;
				}
				Facility* fac = iter1.second;
				fac->Render(s);
				//拾取操作
				if (_tp._bRunEdit
					&& g_input->KeyDown(KeyCode::MOUSE_L)
					&& fac->IsPickup())
				{
					_selectFacility = { x, y };
				}
			}
		}

		//regime
		{
			size_t i = 0;
			for (auto& [uid, regime] : _allRegime)
			{
				regime->RefreshUI(i);
				regime->RenderUI();
				//拾取操作
				if (_tp._bRunEdit
					&& g_input->KeyDown(KeyCode::MOUSE_L)
					&& regime->IsPickup())
				{
					Common::OpenPanelRegime(regime);
				}

				++i;
			}
		}
		

		if (_tp._bRunEdit)
		{
			_render_select();
			_render_brush();
			_render_brush_facility();
		}

		if (md_panel_game->_bRenderGrid)
		{
			_grid.Render();
		}

		if (_msgBoxImportLocation)
			_msgBoxImportLocation->Run(LogicType::RENDER);
	}
}

Node* World::AddNode(const Point& xy)
{
	Node*& node = _allNode.Add(xy);
	if (node == nullptr)
	{
		node = new Node({ xy, 0 });
		node->RefreshUI();
	}
	return node;
}

void World::DeleteNode(const Point& xy)
{
	Node* node = GetNode(xy);
	if (node)
	{
		delete node;
		_allNode.Delete(xy);
	}
}

void World::DeleteFacility(const Point& xy)
{
	Facility* fac = GetFacility(xy);
	if (fac)
	{
		delete fac;
		_allFacility.Delete(xy);
	}
}

void World::DeleteArea(size_t uid)
{
	auto iter = _allArea.find(uid);
	if (iter == _allArea.end())
	{
		debug_warn("未找到区域！");
		return;
	}
	//移除节点引用
	Area* area = iter->second;

	auto& c = area->GetSlRef()._allNode;
	for (auto& iter1 : c.GetContainer())
	{
		for (auto& node : iter1.second)
		{
			Node::TP& tp = node.second->GetTpRef();
			assert(tp._uidArea == area->GetUID());
			tp._uidArea = -1;
		}
	}

	delete iter->second;
	_allArea.erase(iter);
}

constexpr n32 SL_VERSION_TERRAIN_LOW = 0;
constexpr n32 SL_VERSION_TERRAIN = 1;

constexpr n32 SL_VERSION_FACILITY = 0;

constexpr n32 SL_VERSION_AREA_LOW = 1;
constexpr n32 SL_VERSION_AREA = 1;

void World::Save(std::string_view path_name)
{
	n32 version = SL_VERSION_TERRAIN;

	StreamOutput s;
	s.Write(&version);

	//node
	size_t size_y = _allNode.GetYSize();
	s.Write64(&size_y);

	for (auto& iter : _allNode.GetContainer())
	{
		s.Write64(&iter.first);

		size_t size_x = iter.second.size();
		s.Write64(&size_x);

		for (auto& iter1 : iter.second)
		{
			s.Write64(&iter1.first);
			iter1.second->Save(s);
		}
	}

	s.Save(path_name);
}

void World::SaveFacility(std::string_view path_name)
{
	n32 version = SL_VERSION_FACILITY;

	StreamOutput s;
	s.Write(&version);

	//
	size_t size_y = _allFacility.GetYSize();
	s.Write64(&size_y);

	for (auto& iter : _allFacility.GetContainer())
	{
		s.Write64(&iter.first);

		size_t size_x = iter.second.size();
		s.Write64(&size_x);

		for (auto& iter1 : iter.second)
		{
			s.Write64(&iter1.first);
			iter1.second->Save(s);
		}
	}

	s.Save(path_name);
}

void World::SaveArea(string_view path_name)
{
	n32 version = SL_VERSION_AREA;

	StreamOutput s;
	s.Write(&version);

	s.Write64(&_uidArea);
	//
	size_t size = _allArea.size();
	s.Write64(&size);

	for (auto& iter : _allArea)
	{
		iter.second->Save(s);
	}

	s.Save(path_name);
}

void World::Load(string_view path_name)
{
	StreamInput s;
	if (!s.LoadFromFile(path_name))
	{
		debug_err("文件打开失败：" + string{ path_name });
		return;
	}

	n32 version;
	s.Read(&version);

	if (version < SL_VERSION_TERRAIN_LOW)
	{
		debug_err("该存档版本已不支持：" + string{ path_name });
		return;
	}

	//
	size_t size_y;
	s.Read64(&size_y);

	for (size_t j = 0; j < size_y; ++j)
	{
		zahlen y;
		s.Read64(&y);

		size_t size_x;
		s.Read64(&size_x);

		for (size_t i = 0; i < size_x; ++i)
		{
			zahlen x;
			s.Read64(&x);
			Node*& node = _allNode.Add({ x, y });
			assert(node == nullptr);

			node = new Node;

			node->Load(s, version);
			node->RefreshUI();
		}
	}
}

void World::LoadFacility(std::string_view path_name)
{
	StreamInput s;
	if (!s.LoadFromFile(path_name))
	{
		debug_err("文件打开失败：" + string{ path_name });
		return;
	}

	n32 version;
	s.Read(&version);

	if (version != SL_VERSION_FACILITY)
	{
		debug_err("该存档版本已不支持：" + string{ path_name });
		return;
	}

	//
	size_t size_y;
	s.Read64(&size_y);

	for (size_t j = 0; j < size_y; ++j)
	{
		zahlen y;
		s.Read64(&y);

		size_t size_x;
		s.Read64(&size_x);

		for (size_t i = 0; i < size_x; ++i)
		{
			zahlen x;
			s.Read64(&x);
			Facility*& fac = _allFacility.Add({ x, y });
			assert(fac == nullptr);

			fac = new Facility(s, version);
			fac->RefreshUI();
		}
	}
}

void World::LoadArea(string_view path_name)
{
	StreamInput s;
	if (!s.LoadFromFile(path_name))
	{
		debug_err("文件打开失败：" + string{ path_name });
		return;
	}

	n32 version;
	s.Read(&version);

	if (version < SL_VERSION_AREA_LOW)
	{
		debug_err("该存档版本已不支持：" + string{ path_name });
		return;
	}

	//最新版本才读入 area编号
	if(version == SL_VERSION_AREA)
		s.Read64(&_uidArea);

	//
	size_t size;
	s.Read64(&size);

	for (size_t i = 0; i < size; ++i)
	{
		Area* area = new Area(s);
		area->RefreshUI(Area::ALL);
		_allArea.insert(make_pair(area->GetUID(), area));
	}
	//旧版本
	//if (version == SL_VERSION_AREA)
	//{
	//	//计算Area使用uid
	//	for (auto& iter : _allArea)
	//	{
	//		_uidArea = max(_uidArea, iter.first);
	//	}
	//	++_uidArea;
	//}
}

vector<dnd::Point> World::GetBrushXy(zahlen size)
{
	if (size <= 0)
		return {};
	if (size == 1)
	{
		return { GetMouseXy() };
	}
	Vector2 pos = toVector2(g_input->GetMousePosition());
	pos = _coor->WorldToThis(pos);
	if (size % 2 == 0)
		pos += fill_up<Vector2>(DefVar::NODE_PIXEL * 0.5);

	Point xy = Pos2Xy(pos) - Point{ size / 2, size / 2 };

	vector<Point> ret;
	for (zahlen j = 0; j < size; ++j)
		for (zahlen i = 0; i < size; ++i)
		{
			ret.push_back(xy + Point{ i, j });
		}
	return ret;
}

void World::_update_coor()
{
	Vector2 dt{};
	const real speed = 200.0 * g_time->GetRealDelta();

	if (g_input->KeyState(KeyCode::A))
		dt[0] += speed;
	if (g_input->KeyState(KeyCode::D))
		dt[0] -= speed;
	if (g_input->KeyState(KeyCode::W))
		dt[1] += speed;
	if (g_input->KeyState(KeyCode::S))
		dt[1] -= speed;

	_coor->DtPosition(dt);

	int d = g_input->GetMouseWheelDelta();
	if (d != 0)
	{
		//以鼠标位置缩放
		//Vector2 pos0 = toVector2(g_input->GetMousePosition());

		//以窗口中心缩放
		Vector2 pos0 = toVector2(g_system->GetWindowSize()) * 0.5;
		Vector2 pos_in_map = _coor->WorldToThis(pos0);

		_curScaleLevel = add_u(_curScaleLevel, d);
		_curScaleLevel = Math::Limit(_curScaleLevel, (size_t)0, SCALE_LEVEL_ALL.size() - 1);
		_coor->SetScale(SCALE_LEVEL_ALL[_curScaleLevel]);

		Vector2 pos1 = _coor->ThisToWorld(pos_in_map);
		_coor->DtPosition(pos0 - pos1);
	}
}

void World::_update_select(zahlen size)
{
	if (size == 4)
		size = 10;

	_tp._mulSelect = GetBrushXy(size);

	if (_tp._mulSelect.size() > _mulSprSelect.size())
	{
		_mulSprSelect.resize(_tp._mulSelect.size());
		for (auto& iter : _mulSprSelect)
		{
			if (!iter)
			{
				iter = g_factory->CreateSprite("select");
				iter->SetCoor(_coor);
			}
		}
	}

	for (size_t i = 0; i < _tp._mulSelect.size(); ++i)
	{
		_mulSprSelect[i]->SetQuad(_quadSelect + Xy2Pos(_tp._mulSelect[i]));
	}

}

void World::_update_brush(zahlen index, bool b_edit_water, bool b_new_node)
{
	if (index < 0
		|| !_tp._bRunEdit
		|| _tp._mulSelect.empty())
	{
		_sprBrush.CancelRef();
		return;
	}

	//删除节点
	bool b_delete = (index >= g_db->GetTerrainRef().size());

	_sprBrush = g_factory->CreateSprite("terrain", index);
	_sprBrush->SetQuad(_sprBrush->GetQuad() + toVector2(g_input->GetMousePosition()));

	if (g_input->KeyState(KeyCode::MOUSE_L))
	{
		if (b_delete)
		{
			for (auto& iter : _tp._mulSelect)
			{
				//更新纹理地图
				_mapTex.Set(Xy2MapTex(iter), g_factory->GetColor("terrain_ocean"));
				DeleteNode(iter);
			}
		}
		else
		{
			for (auto& iter : _tp._mulSelect)
			{
				Node* node = b_new_node ? AddNode(iter) : GetNode(iter);
				if (node == nullptr)
				{
					continue;
				}

				Node::SL& sl = node->GetSlRef();

				if (!b_edit_water
					&& (sl._typeTerrain == g_db->GetTerrainId("ocean")
						|| sl._typeTerrain == g_db->GetTerrainId("water")))
					continue;

				sl._typeTerrain = index;
				node->RefreshUI();
			}
		}

	}
}

void World::_update_brush_facility(zahlen index, bool b_delete)
{

	if (index == 0)
	{//定居 location
		_sprBrushFacility = g_factory->CreateSprite("location", 0);
		_sprBrushFacility->SetQuad(_sprBrushFacility->GetQuad() + toVector2(g_input->GetMousePosition()));

		if (g_input->KeyState(KeyCode::MOUSE_L))
		{
			Facility* fac = AddFacility(GetMouseXy(), 0);
		}
	}
	else
	{
		if (b_delete)
		{
			if (g_input->KeyState(KeyCode::MOUSE_L))
			{
				DeleteFacility(_selectFacility);
			}
		}

		_sprBrushFacility.CancelRef();
	}
}

void World::_import_location(natural tag)
{
	for (auto& iter : g_db->GetLocationRef())
	{
		if (tag == 1)
		{//保留原有
			Facility* fac = GetFacility(iter._xy);
			if (fac)
			{
				debug("跳过一个设施（已存在）：" + fac->GetData().GetName());
				continue;
			}
		}

		//添加（修改）一个
		Facility* fac = AddFacility(iter._xy, FacilityLocation::GetClassID());

		if (FacilityLocation* location = fac->GetData().Cast<FacilityLocation>())
		{
			location->_name = iter._name;
			location->_type = 0;
			location->RefreshUI();
		}
	}
}

void World::_update_area(size_t index)
{
	if (index < 1)
		return;

	if (index == 1)
	{//新增
		if (g_input->KeyUp(KeyCode::MOUSE_L))
		{
			size_t uid = _uidArea++;
			Area* area = new Area(uid);
			if (area->Add(GetMouseXy(), true))
			{
				area->RefreshUI(Area::Refresh::ALL);
				_allArea.insert({ uid, area });
				//设为当前操作
				_uidAreaSelect = uid;
			}
			else
				delete area;

		}
	}
	else if (index == 2)
	{//修改
		if (g_input->KeyState(KeyCode::MOUSE_L))
		{
			Area* area = GetSelectArea();
			if (area)
			{
				if (area->Add(GetMouseXy(), true))
					area->RefreshUI(Area::Refresh::AREA);
			}
		}
		else if (g_input->KeyState(KeyCode::MOUSE_R))
		{//右键为移除
			Area* area = GetSelectArea();
			if (area)
			{
				if (area->Remove(GetMouseXy()))
					area->RefreshUI(Area::Refresh::AREA);
			}
		}
	}
	else if (index == 3)
	{//移除整个区域
		if (g_input->KeyUp(KeyCode::MOUSE_L))
		{
			Area* area = GetSelectArea();
			if (area)
			{
				DeleteArea(area->GetUID());
			}
		}
	}
}
